package com.everyline.lib_base.view

import android.content.Context
import android.graphics.*
import android.util.AttributeSet
import android.view.Gravity
import android.view.MotionEvent
import android.view.View
import android.view.ViewGroup
import com.blankj.utilcode.util.SizeUtils
import com.everyline.lib_base.R

/**
 * Created by Gnepux on 16/12/29.
 */
class SlideView @JvmOverloads constructor(context: Context, attrs: AttributeSet? = null) :
    ViewGroup(context, attrs) {
    // SlideIcon实例
    private var mSlideIcon: SlideIcon? = null

    // SlideIcon的X坐标
    private var mIconX = 0

    // SlideIcon拖动时的X轴偏移量
    private var mDistanceX = 0

    // 监听
    private var mMotionListener: MotionListener? = null

    // 背景文字的Paint
    private var mBgTextPaint: Paint? = null

    // 背景文字的测量类
    private var mBgTextFontMetrics: Paint.FontMetrics? = null

    // 拖动过的部分的Paint
    private var mSecondaryPaint: Paint? = null

    // attr: 最小高度
    private var mMinHeight = 0

    // attr: 背景图
    private var mBgResId = 0

    // attr: 背景文字
    private var mBgText: String? = ""

    // attr: 拖动完成后的背景文字
    private var mBgTextComplete: String? = ""

    // attr: 背景文字的颜色
    private var mBgTextColor = 0

    // attr: 背景文字的大小
    private var mBgTextSize = 0f

    // attr: Icon背景图
    private var mIconResId = 0

    // attr: Icon上显示的文字
    private var mIconText: String? = ""

    // attr: Icon上文字的颜色
    private var mIconTextColor = 0

    // attr: Icon上文字的大小
    private var mIconTextSize = 0f

    // attr: Icon的宽度占总长的比例
    private var mIconRatio = 0f

    // attr: 滑动到一半松手时是否回到初始状态
    var isResetWhenNotFull = false
        private set

    // attr: 拖动结束后是否可以再次操作
    var isEnableWhenFull = false
        private set

    // attr: 拖动过的部分的颜色
    private var mSecondaryColor = 0

    // attr: 背景文字渐变色1
    private var mGradientColor1 = 0

    // attr: 背景文字渐变色1
    private var mGradientColor2 = 0

    // attr: 背景文字渐变色1
    private var mGradientColor3 = 0
    private var mListener: OnSlideListener? = null
    private var mTextView: CustTextView? = null

    // 控件滑动的回调
    interface OnSlideListener {
        /**
         * 滑动完成的回调
         */
        fun onSlideSuccess()
    }

    private fun init() {
        // 设置背景文字Paint
        mBgTextPaint = Paint()
        mBgTextPaint!!.textAlign = Paint.Align.CENTER
        mBgTextPaint!!.color = mBgTextColor
        mBgTextPaint!!.textSize = mBgTextSize

        // 获取背景文字测量类
        mBgTextFontMetrics = mBgTextPaint!!.fontMetrics

        // 设置拖动过的部分的Paint
        mSecondaryPaint = Paint()
        mSecondaryPaint!!.color = mSecondaryColor

        // 设置背景图
        setBackgroundResource(mBgResId)
        mTextView = CustTextView(context)
        mTextView!!.text = mBgText
        val layoutParams = LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT)
        mTextView!!.layoutParams = layoutParams
        mTextView!!.gravity = Gravity.CENTER
        mTextView!!.setTextColor(Color.WHITE)
        mTextView!!.textSize = 14f
        addView(mTextView)

        // 创建一个SlideIcon,设置LayoutParams并添加到ViewGroup中
        mSlideIcon = SlideIcon(context)
        /**
         * Important:
         * 此处需要设置IconView的LayoutParams,这样才能在布局文件中正确通过wrap_content设置布局
         */
        mSlideIcon!!.layoutParams =
            LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.MATCH_PARENT)
        addView(mSlideIcon)

        // 设置监听
        mMotionListener = object : MotionListener {
            override fun onActionMove(distanceX: Int) {
                // SlideIcon拖动时根据X轴偏移量重新计算位置并绘制
                if (mSlideIcon != null) {
                    mDistanceX = distanceX
                    requestLayout()
                    invalidate()
                }
            }

            override fun onActionUp(x: Int) {
                mIconX = x
                mDistanceX = 0
                if (mIconX + mSlideIcon!!.measuredWidth < measuredWidth - SizeUtils.dp2px(30f)) {  // SlideIcon为拖动到底
                    if (isResetWhenNotFull) {  // 重置
                        mIconX = 0
                        mSlideIcon!!.resetIcon()
                        requestLayout()
                        invalidate()
                    }
                } else {  // SlideIcon拖动到底
                    if (!isEnableWhenFull) {  // 松开后是否可以继续操作
                        mSlideIcon!!.enable = false
                    }
                    if (mListener != null) {  // 触发回调
                        mListener!!.onSlideSuccess()
                    }
                }
            }
        }
        mSlideIcon!!.setListener(mMotionListener)
    }

    fun addSlideListener(listener: OnSlideListener?) {
        mListener = listener
    }

    fun reset() {
        mIconX = 0
        mDistanceX = 0
        if (mSlideIcon != null) {
            mSlideIcon!!.resetIcon()
        }
        requestLayout()
        invalidate()
    }

    fun enableWhenFull(enable: Boolean) {
        isEnableWhenFull = enable
    }

    fun resetWhenNotFull(reset: Boolean) {
        isResetWhenNotFull = reset
    }

    fun setmBgText(text: String?) {
        mBgText = text
        mTextView!!.text = text
        invalidate()
    }

    fun setBgResId(bgResId: Int) {
        mBgResId = bgResId
        setBackgroundResource(mBgResId)
        invalidate()
    }

    fun setIcon_drawable(icon_drawable: Int) {
        mIconResId = icon_drawable
        mSlideIcon!!.setBackgroundResource(icon_drawable)
        invalidate()
    }

    fun setSecondaryColor(secondaryColor: Int) {
        mSecondaryColor = secondaryColor
        mSecondaryPaint!!.color = mSecondaryColor
        invalidate()
    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        // 计算子View的尺寸
        measureChildren(widthMeasureSpec, heightMeasureSpec)
        // 因为只有一个子View,直接取出来
        mTextView = getChildAt(0) as CustTextView
        mSlideIcon = getChildAt(1) as SlideIcon
        // 根据SlideIcon的高度设置ViewGroup的高度
        setMeasuredDimension(widthMeasureSpec, mSlideIcon!!.measuredHeight)
    }

    override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
        if (mIconX + mDistanceX <= 0) { // 控制SlideIcon不能超过左边界限
            mSlideIcon!!.layout(
                MARGIN_HORIZONTAL, MARGIN_VERTICAL,
                MARGIN_HORIZONTAL + mSlideIcon!!.measuredWidth,
                mSlideIcon!!.measuredHeight - MARGIN_VERTICAL
            )
        } else if (mIconX + mDistanceX + mSlideIcon!!.measuredWidth >= measuredWidth) { // 控制SlideIcon不能超过左边界限
            mSlideIcon!!.layout(
                measuredWidth - mSlideIcon!!.measuredWidth - MARGIN_HORIZONTAL, MARGIN_VERTICAL,
                measuredWidth - MARGIN_HORIZONTAL,
                mSlideIcon!!.measuredHeight - MARGIN_VERTICAL
            )
        } else {  // 根据SlideIcon的X坐标和偏移量计算位置
            mSlideIcon!!.layout(
                mIconX + mDistanceX + MARGIN_HORIZONTAL, MARGIN_VERTICAL,
                mIconX + mDistanceX + mSlideIcon!!.measuredWidth + MARGIN_HORIZONTAL,
                mSlideIcon!!.measuredHeight - MARGIN_VERTICAL
            )
        }
        val l = measuredWidth / 2 - mTextView!!.measuredWidth / 2
        val t = measuredHeight / 2 - mTextView!!.measuredHeight / 2
        val r = measuredWidth / 2 + mTextView!!.measuredWidth / 2
        val b = measuredHeight / 2 + mTextView!!.measuredHeight / 2
        mTextView!!.layout(l, t, r, b)
    }

    override fun onDraw(canvas: Canvas) {
        super.onDraw(canvas)

        // 绘制已拖动过的区域
        if (mIconX + mDistanceX > 0) {
            val rectF = RectF(
                MARGIN_HORIZONTAL.toFloat(),
                MARGIN_VERTICAL.toFloat(),
                (mIconX + mDistanceX + MARGIN_HORIZONTAL + mSlideIcon!!.measuredHeight / 2).toFloat(),
                (measuredHeight - MARGIN_VERTICAL).toFloat()
            )
            canvas.drawRoundRect(rectF, 12f, 12f, mSecondaryPaint!!)
            //            canvas.drawRect(MARGIN_HORIZONTAL, MARGIN_VERTICAL, mIconX + mDistanceX + MARGIN_HORIZONTAL + mSlideIcon.getMeasuredHeight() / 2,
//                    getMeasuredHeight() - MARGIN_VERTICAL, mSecondaryPaint);
        }

        // 绘制背景文字
//        float baselineY = (getMeasuredHeight() - mBgTextFontMetrics.top - mBgTextFontMetrics.bottom) / 2;
        if (mIconX + mDistanceX + mSlideIcon!!.measuredWidth >= measuredWidth) {
//            canvas.drawText(mBgTextComplete == null ? "":mBgTextComplete, getMeasuredWidth() / 2, baselineY, mBgTextPaint);
            mTextView!!.text = mBgTextComplete
        } else {
//            canvas.drawText(mBgText == null ? "":mBgText, getMeasuredWidth() / 2, baselineY, mBgTextPaint);
            mTextView!!.text = mBgText
        }
    }

    /**
     * 可拖动的View
     */
    private inner class SlideIcon @JvmOverloads constructor(
        context: Context?,
        attrs: AttributeSet? = null
    ) : View(context, attrs) {
        // 用来控制触摸事件是否可用
        var enable = false

        // 提示文字的Paint
        private var mTextPaint: Paint? = null

        // 提示文字的字体测量类
        private var mFontMetrics: Paint.FontMetrics? = null

        // 回调
        private var listener: MotionListener? = null

        // 手指按下时SlideIcon的X坐标
        private var mDownX = 0f

        // SlideIcon在非拖动状态下的X坐标
        private var mX = 0f

        // SliedIcon在拖动状态下X轴的偏移量
        private var mDistanceX = 0f
        fun setListener(listener: MotionListener?) {
            this.listener = listener
        }

        private fun init() {
            // 设置文字Paint
            mTextPaint = Paint()
            mTextPaint!!.textAlign = Paint.Align.CENTER
            mTextPaint!!.color = mIconTextColor
            mTextPaint!!.textSize = mIconTextSize

            // 获取字体测量类
            mFontMetrics = mTextPaint!!.fontMetrics

            // 设置背景图
            setBackgroundResource(mIconResId)

            // 设置可用
            enable = true
        }

        /**
         * 重置SlideIcon
         */
        fun resetIcon() {
            mDownX = 0f
            mDistanceX = 0f
            mX = 0f
            enable = true
        }

        override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
            // 宽度和宽Mode
            val widthSize = MeasureSpec.getSize(widthMeasureSpec)
            val widthMode = MeasureSpec.getMode(widthMeasureSpec)

            // 高度和高Mode
            val heightSize = MeasureSpec.getSize(heightMeasureSpec)
            val heightMode = MeasureSpec.getMode(heightMeasureSpec)
            when (heightMode) {
                MeasureSpec.AT_MOST -> setMeasuredDimension(
                    MeasureSpec.makeMeasureSpec(
                        (widthSize * mIconRatio).toInt(), widthMode
                    ),
                    MeasureSpec.makeMeasureSpec(mMinHeight, heightMode)
                )
                else -> setMeasuredDimension(
                    MeasureSpec.makeMeasureSpec((widthSize * mIconRatio).toInt(), widthMode),
                    MeasureSpec.makeMeasureSpec(heightSize, heightMode)
                )
            }
        }

        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)

            // 获取文字baseline的Y坐标
            val baselineY = (measuredHeight - mFontMetrics!!.top - mFontMetrics!!.bottom) / 2
            // 绘制文字
            if (mIconText == null) "" else mIconText?.let {
                canvas.drawText(
                    it,
                    (measuredWidth / 2).toFloat(),
                    baselineY,
                    mTextPaint!!
                )
            }
        }

        override fun onTouchEvent(event: MotionEvent): Boolean {
            return if (enable) {
                if (event.action == MotionEvent.ACTION_DOWN) {
                    // 记录手指按下时SlideIcon的X坐标
                    mDownX = event.rawX
                    return true
                } else if (event.action == MotionEvent.ACTION_UP) {
                    // 设置手指松开时SlideIcon的X坐标
                    mDownX = 0f
                    mX = mX + mDistanceX
                    mDistanceX = 0f
                    // 触发松开回调并传入当前SlideIcon的X坐标
                    if (listener != null) {
                        listener!!.onActionUp(mX.toInt())
                    }
                    return true
                } else if (event.action == MotionEvent.ACTION_MOVE) {
                    // 记录SlideIcon在X轴上的拖动距离
                    mDistanceX = event.rawX - mDownX
                    // 触发拖动回调并传入当前SlideIcon的拖动距离
                    if (listener != null) {
                        listener!!.onActionMove(mDistanceX.toInt())
                    }
                    return true
                }
                false
            } else {
                true
            }
        }

        init {
            init()
        }
    }

    /**
     * 触摸事件的回调
     */
    private interface MotionListener {
        /**
         * 拖动时的回调
         * @param distanceX SlideIcon的X轴偏移量
         */
        fun onActionMove(distanceX: Int)

        /**
         * 松开时的回调
         * @param x SlideIcon的X坐标
         */
        fun onActionUp(x: Int)
    }

    private inner class CustTextView : androidx.appcompat.widget.AppCompatTextView {
        private var mViewWith = 0
        private var mTranleate = 0
        private var mPaint: Paint? = null
        private var mLinearGradient: LinearGradient? = null
        private var mMatrix: Matrix? = null

        constructor(context: Context) : super(context, null) {}
        constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {}

        override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
            super.onSizeChanged(w, h, oldw, oldh)
//            if (mViewWith == 0) {
//                mViewWith = measuredWidth
//                if (mViewWith > 0) {
//                    mPaint = paint
//                    /**
//                     * LinearGradient第一个和第二个参数表示颜色渐变的起点 第三、第四表示颜色渐变的终点 第五个参数表示渐变的颜色
//                     * 第六个参数可以为空,表示坐标,值为0-1 new float[] {0.25f, 0.5f, 0.75f, 1 }
//                     * 如果这是空的，颜色均匀分布，沿梯度线
//                     * 第七个表示平铺方式
//                     * CLAMP重复最后一个颜色至最后
//                     * MIRROR重复着色的图像水平或垂直方向已镜像方式填充会有翻转效果
//                     * REPEAT重复着色的图像水平或垂直方向
//                     */
//                    mLinearGradient = LinearGradient(
//                        0f,
//                        0f,
//                        mViewWith.toFloat(),
//                        0f,
//                        intArrayOf(mGradientColor1, mGradientColor2, mGradientColor3),
//                        null,
//                        Shader.TileMode.MIRROR
//                    )
//                    mPaint?.shader = mLinearGradient
//                    mMatrix = Matrix()
//                }
//            }
        }

        override fun onDraw(canvas: Canvas) {
            super.onDraw(canvas)
            if (mMatrix != null) {
                mTranleate += mViewWith / 14
                if (mTranleate > 2 * mViewWith) {
                    mTranleate = -mViewWith
                }
                mMatrix!!.setTranslate(mTranleate.toFloat(), 0f)
                mLinearGradient!!.setLocalMatrix(mMatrix)
                postInvalidateDelayed(250)
            }
        }
    }

    companion object {
        private const val TAG = "SlideView"

        // SlideIcon在父view中的水平偏移量
        private const val MARGIN_HORIZONTAL = 0

        // SlideIcon在父view中的水平便宜量
        private const val MARGIN_VERTICAL = 0
    }

    init {
        val a = context.theme.obtainStyledAttributes(attrs, R.styleable.SlideView, 0, 0)
        try {
            isResetWhenNotFull = a.getBoolean(R.styleable.SlideView_reset_not_full, true)
            isEnableWhenFull = a.getBoolean(R.styleable.SlideView_enable_when_full, false)
            mBgResId =
                a.getResourceId(R.styleable.SlideView_bg_drawable, android.R.drawable.btn_default)
            mIconResId =
                a.getResourceId(R.styleable.SlideView_icon_drawable, android.R.drawable.btn_default)
            mMinHeight = a.getDimensionPixelSize(R.styleable.SlideView_min_height, 240)
            mIconText = a.getString(R.styleable.SlideView_icon_text)
            mIconTextColor = a.getColor(R.styleable.SlideView_icon_text_color, Color.WHITE)
            mIconTextSize =
                a.getDimensionPixelSize(R.styleable.SlideView_icon_text_size, 44).toFloat()
            mIconRatio = a.getFloat(R.styleable.SlideView_icon_ratio, 0.2f)
            mBgText = a.getString(R.styleable.SlideView_bg_text)
            mBgTextComplete = a.getString(R.styleable.SlideView_bg_text_complete)
            mBgTextColor = a.getColor(R.styleable.SlideView_bg_text_color, Color.BLACK)
            mBgTextSize = a.getDimensionPixelSize(R.styleable.SlideView_bg_text_size, 44).toFloat()
            mSecondaryColor = a.getColor(R.styleable.SlideView_secondary_color, Color.TRANSPARENT)
            mGradientColor1 = a.getColor(R.styleable.SlideView_gradient_color1, Color.WHITE)
            mGradientColor2 = a.getColor(R.styleable.SlideView_gradient_color2, Color.WHITE)
            mGradientColor3 = a.getColor(R.styleable.SlideView_gradient_color3, Color.WHITE)
        } finally {
            a.recycle()
        }
        init()
    }
}